#ifndef Field_First
#define Field_First
#ifdef __GNUG__
#pragma interface
#endif

#include "VObject.h"

class Clipper;
class RegularExp;
class TextView;
class EditField;
class Text;

enum EditFieldFlags {
	eEditFieldHasOverlay = BIT(eVObjLast+1),
	eEditFieldNoBorder   = BIT(eVObjLast+2),
	eEditFieldAutoSize   = BIT(eVObjLast+3),
	eEditFieldDefault    = eVObjDefault,
	eEditFieldLast       = eVObjLast+3
};

//---- TextViewOverlay ---------------------------------------------------------

class TextViewOverlay {
	Clipper *cl;
	TextView *tv;
	EditField *currentfield;
	Text *ct;
	bool noupdate;
public:
	TextViewOverlay();
	~TextViewOverlay();
	bool Draw(EditField *ef, Rectangle r);
	void Update(EditField *ef);
	void SetOrigin(EditField *ef, Point at);
	void SetExtent(EditField *ef, Point e);
	Command *DispatchEvents(EditField *ef, Point lp, Token &t, Clipper *vf);
	bool KbdFocus(EditField *ef, bool in, bool wordwrap);
	bool CopyInStr(EditField *ef, char *buf, int sz);
	bool Size(EditField *ef, int *sz);
	bool Sync(EditField *ef);
	void DoSetupMenu(EditField *ef, Menu*);
	Command *DoMenuCommand(EditField *, int c);
	Text *GetOverlayText(const char *s= "");
	TextView *GetOverlayTextView()
    	{ return tv; }
};

//---- Field -------------------------------------------------------------------

class Field : public VObject {
public:
	MetaDef(Field);

	Field(int minwidth= 0, Font *f= gSysFont);
	Field(int id, int minwidth= 0, Font *f= gSysFont);
	void Init(int mw, Font *f);

	Metric GetMinSize();
	void SetEditable(bool e);
	Font *GetFont()
		{ return font; }
	void SetFont(Font *fp);
	void Draw(Rectangle);
	virtual const char *GetStringForDrawing();
	int Compare(Object *op);
	bool IsEqual(Object *op);
	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);

protected:
	virtual int GetLines();
	Font *font;
	int minwidth;
};

//---- EditField ---------------------------------------------------------------

class EditField: public Field {
public:
	MetaDef(EditField);

	EditField(int id, int minwidth= 0, Font *f= gSysFont);
	~EditField();

	TextViewOverlay *GetTextViewOverlay();
	void Enable(bool b= TRUE, bool redraw= TRUE);
	void Draw(Rectangle);
	bool KbdFocus(bool in);
	virtual bool ValidateString(const char *s);
	Command *Input(Point lp, Token &t, Clipper *vf);
	Command *DispatchEvents(Point lp, Token &t, Clipper *vf);
	void SetOrigin(Point at);
	void SetExtent(Point e);
	void Control(int id, int part, void *val);
	virtual const char *GetStringForEditing();
	void Update(bool redraw);
	bool HasOverlay()
		{ return TestFlag(eEditFieldHasOverlay); }
	void Sync();
	void DoSetupMenu(Menu*);
	Command *DoMenuCommand(int c);
	void Open(bool mode);
};

//---- TextField ---------------------------------------------------------------

class TextField: public EditField {
public:
	MetaDef(TextField);

	TextField(int id, int minWidthInChars, Font *f= gSysFont);
	TextField(int id, const char *t, Font *f= gSysFont);
	~TextField();
	const char *AsString();
	void SetString(const char*, bool redraw= FALSE);
	void SetFString(bool redraw, const char *fmt, ...);
	bool ValidateString(const char *s);
	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);

	//obsolete; for compatibility with EditTextItem
	TextField(int id, int minWidthInPixel, const char *t);
	int GetTextSize();
	void GetString(char *buf, int sz);
	const char *GetString();
protected:
	char *text;
};

//---- MultiLineField ----------------------------------------------------------

class MultiLineField : public TextField {
public:
	MetaDef(MultiLineField);
	MultiLineField(int id, int l, int minwidth= 0, const char *t="");

	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);
protected:
	int GetLines();

	int lines;
};

//---- FormatField -------------------------------------------------------------

class FormatField: public EditField {
public:
	MetaDef(FormatField);

	FormatField(int id, const char *fmt);
	~FormatField();
	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);
protected:
	char *format;
};

//---- IntField ----------------------------------------------------------------

class IntField: public FormatField {
public:
	MetaDef(IntField);

	IntField(int id, int minval= -cMaxInt, int maxval= cMaxInt, const char *fmt= "%d");
	IntField(int id, int val, int minval, int maxval, const char *fmt= "%d");
	void Init(int val, int minval, int maxval);
	int GetValue();
	bool SetValue(int, bool redraw= TRUE);
	void SetRange(int min, int max);
	void GetRange(int &min, int &max);
	bool ValidateString(const char *s);
	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);
	const char *AsString();
	const char *GetStringForDrawing();
protected:
	int value, minVal, maxVal;
};

//---- FloatField --------------------------------------------------------------

class FloatField: public FormatField {
public:
	MetaDef(FloatField);

	FloatField(int id, double minval, double maxval, const char *fmt= "%g");
	FloatField(int id, double val, double minval, double maxval, const char *fmt= "%g");
	void Init(double val, double minval, double maxval);
	double GetValue();
	bool SetValue(double, bool redraw= TRUE);
	void SetRange(double min, double max);
	void GetRange(double &min, double &max);
	bool ValidateString(const char *s);
	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);
	const char *AsString();
	const char *GetStringForDrawing();
protected:
	double value, minVal, maxVal;
};

//---- RegExpField -------------------------------------------------------------


class RegExpField : public TextField {
public:
	MetaDef(RegExpField);
	RegExpField(int id, RegularExp *rex, int mw= 0, const char *msg= 0,
															const char *t= "");
	~RegExpField();

	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);
protected:
	bool ValidateString(const char *s);
private:
	RegularExp *regex;
	char *errmsg;
};

#endif

